package com.myk.game.gobangchess.rooms;

import com.myk.game.gobangchess.Room;
import com.myk.game.gobangchess.constants.BoardStyleData;
import com.myk.game.gobangchess.constants.ColorCost;
import com.myk.game.gobangchess.constants.WinMode;
import com.myk.game.gobangchess.signs.AroundSign;
import com.myk.game.gobangchess.signs.ColorSign;
import com.myk.game.gobangchess.signs.GroundSign;

import java.util.*;

/**
 * 蜘蛛四子棋
 */
public class SpiderConnect4Room extends Room {


    public SpiderConnect4Room(String roomName) {
        super(roomName, "脑王上的蜘蛛四子棋", "蜘蛛四子棋",BoardStyleData.getGoBangStyle(8,8), true, true);
    }

    @Override
    public String getRuleText() {
        return "黑白双方轮流行动，只能在四周最靠边的位置落子，程序会显示你能落子的位置。形成四子一线获胜。";
    }

    @Override
    public String getCoordMode() {
        return "33330000";
    }

    @Override
    protected void onStartPrepare() {
        signList.clear();
        signList.add(new ColorSign(getCanPutIndexes(), ColorCost.NEW_PUT_POINT_LIGHT));
        noticeBlackMove(); //默认通知黑方先行动
    }

    @Override
    public void doRule(int row, int col, int value) {
        if (getCanPutIndexes().contains(getIndex(row,col))) { //在允许落子的地方落子时
            curGrids[row][col] = value;
            signList.clear();
            signList.add(new AroundSign(getIndex(row, col), "#00000000", ColorCost.NEW_PUT_POINT, 1.2f));
            signList.add(new ColorSign(getCanPutIndexes(), ColorCost.NEW_PUT_POINT_LIGHT));
            checkWin(value);
        }
    }

    //获取可以落子的坐标集合
    private List<Integer> getCanPutIndexes() {
        int maxRow = curGrids.length;
        int maxCol = curGrids[0].length;
        Set<Integer> indexes = new HashSet<>();
        for (int i = 0; i < maxRow; i++) {
            for (int j = 0; j < maxCol; j++) {
                if (curGrids[i][j] == 0) {
                    indexes.add(getIndex(i, j));
                    break;
                }
            }
            for (int j = maxCol - 1; j >= 0; j--) {
                if (curGrids[i][j] == 0) {
                    indexes.add(getIndex(i, j));
                    break;
                }
            }
        }
        for (int i = 0; i < maxCol; i++) {
            for (int j = 0; j < maxRow; j++) {
                if (curGrids[j][i] == 0) {
                    indexes.add(getIndex(j, i));
                    break;
                }
            }
            for (int j = maxCol - 1; j >= 0; j--) {
                if (curGrids[j][i] == 0) {
                    indexes.add(getIndex(j, i));
                    break;
                }
            }
        }
        return new ArrayList<>(indexes);
    }

    //切换行动方
    private void changeMover(int value) {
        if (value == 1) {
            stepAdd();
            noticeWhiteMove();
        } else if (value == 2) {
            stepAdd();
            noticeBlackMove();
        }
    }

    //获胜判断
    public void checkWin(int value) {
        boolean bH4 = false;
        boolean wH4 = false;
        boolean gridFull = true;
        for (int dx = -1; dx <= 1; dx++) {
            for (int dy = -1; dy <= 1; dy++) {
                if (dx == 0 && dy == 0) {
                    continue;
                }
                for (int x = 0; x <= curGrids[0].length - 1; x++) {
                    for (int y = 0; y <= curGrids[0].length - 1; y++) {
                        if (curGrids[x][y] == 0) {
                            gridFull = false;
                        }
                        int len = getJudgeLength(x, y, dx, dy) + getJudgeLength(x, y, -dx, -dy) - 1;
                        if (len == 4) {
                            if (curGrids[x][y] == 1) {
                                bH4 = true;
                            } else if (curGrids[x][y] == 2) {
                                wH4 = true;
                            }
                        }
                    }
                }
            }
        }
        if (bH4){
            doOver(WinMode.BLACK_WIN, player_black.getNickNameOrTemp() + "执黑棋战胜" + player_white.getNickNameOrTemp());
        }
        else if (wH4){
            doOver(WinMode.WHITE_WIN, player_white.getNickNameOrTemp() + "执白棋战胜" + player_black.getNickNameOrTemp());
        }
        else if (gridFull){
            doOver(WinMode.BOTH_DRAW, player_black.getNickNameOrTemp() + "-黑棋战平" + player_white.getNickNameOrTemp() + "-白棋");
        }
        else {
            changeMover(value);
        }
    }

    protected int getJudgeLength(int x, int y, int dx, int dy) {
        int value = curGrids[x][y];
        int length = 0;
        while (isInGrids(x, y)) {
            if (curGrids[x][y] != value) {
                return length;
            }
            length++;
            x += dx;
            y += dy;
        }
        return length;
    }

    protected boolean isInGrids(int row, int col) {
        return row >= 0 && row <= curGrids.length - 1 && col >= 0 && col <= curGrids[0].length - 1;
    }
}
